﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;

namespace Common.Json
{
    /// <summary>
    /// 时间格式转换
    /// </summary>
    public class DateTimeFormatConverter : JsonConverter
    {
        private readonly string DateTimeFormat;
        /// <summary>
        /// 本地化信息
        /// </summary>
        public CultureInfo Culture { get; set; }
        /// <summary>
        /// 时间转换器
        /// </summary>
        /// <param name="format"></param>
        public DateTimeFormatConverter(string format = "yyyy-MM-dd HH:mm:ss")
        {
            this.DateTimeFormat = format;
            this.Culture = CultureInfo.CurrentCulture;
        }
        /// <inheritdoc/>
        public override bool CanConvert(Type objectType)
        {
            Type[] supportTypes = new Type[]
            {
                typeof(DateTime),typeof(DateTime?),typeof(DateTimeOffset),typeof(DateTimeOffset?)
            };
            return supportTypes.Contains(objectType);
        }
        /// <inheritdoc/>
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
        {
            bool nullable = IsNullable(objectType);
            string dateText = reader.Value?.ToString();
            if (string.IsNullOrEmpty(dateText))
            {
                return nullable ? (object)null : throw new InvalidDataException($"无法将空值转换为{objectType.Name}对象，Key={reader.Path}");
            }
            DateTime dt = Convert.ToDateTime(dateText);
            var t = nullable ? Nullable.GetUnderlyingType(typeof(DateTimeOffset)) : objectType;
            return t == typeof(DateTimeOffset) ? new DateTimeOffset(dt) : (object)dt;
        }
        /// <inheritdoc/>
        public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
        {
            string text;

            if (value is DateTime dateTime)
            {
                text = dateTime.ToString(DateTimeFormat, Culture);
            }
            else if (value is DateTimeOffset dateTimeOffset)
            {
                text = dateTimeOffset.ToString(DateTimeFormat, Culture);
            }
            else
            {
                throw new JsonSerializationException(string.Format("Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {0}.", CultureInfo.InvariantCulture, value.GetType().Name));
            }

            writer.WriteValue(text);
        }
        private static bool IsNullable(Type objectType)
        {
            return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(Nullable<>);
        }
    }
}
